package com.jielihaofeng.springboot.websocket.config;

import com.alibaba.fastjson.JSONObject;
import com.jielihaofeng.springboot.websocket.pojo.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @author Johnnie Wind
 * @description
 * @date 2021/4/2 15:23
 */
@Component
@ServerEndpoint(value = "/connectWebSocket/{userId}")
public class WebSocket {

    // 日志
    private Logger logger = LoggerFactory.getLogger(WebSocket.class);

    // 在线人数
    private static int onlineNumber = 0;

    // 用户 WebSocket 对象存储map
    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();

    // 会话 Session （此处是websocket session）
    private Session session;

    // 用户名
    private String userId;

    // 消息记录
//    private static Map<String,List<Message>> msgs = Maps.newConcurrentMap();

    private static CopyOnWriteArrayList<Message> messageList = new CopyOnWriteArrayList<Message>();

    //建立连接
    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) {
        onlineNumber++;
        logger.info("现在来连接的Session ID：" + session.getId() + "用户ID：" + userId);
        this.userId = userId;
        this.session = session;
        try {
            // messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
            // 给所有人发通知说我上线了
//            Map<String, Object> map1 = Maps.newHashMap();
//            map1.put("messageType", 1);
//            map1.put("userId", userId);
//            sendMessageAll(JSON.toJSONString(map1), userId);

            // 构建消息，放入消息列表存储起来
//            String tos = clients.keySet().stream().collect(Collectors.joining(","));
//            Message message = new Message(userId + MessageType.ONLINE.getKey(),userId,tos,new Date());
//            saveMessage(message);

            // 把自己加入到map里面去
            clients.put(userId, this);
            logger.info("有连接加入！当前在线人数：" + clients.size());

            // 连接后把历史记录消息发送过去
            sendMessageAll(JSONObject.toJSONString(messageList),userId);

            // 给自己发一条消息：告诉自己现在都有谁在线
//            Map<String, Object> map2 = Maps.newHashMap();
//            map2.put("messageType", 3);
//            // 其他在线人有哪些，移除掉自己
//            Set<String> set = clients.keySet();
//            map2.put("onlineUsers", set);
//            sendMessageTo(JSON.toJSONString(map2), userId);
        } catch (Exception e) {
            logger.error(userId + "上线的时间通知所有人发生错误", e.getMessage());
            e.printStackTrace();
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("服务端发生了错误", error.getMessage());
        error.printStackTrace();
    }

    @OnClose
    public void onClose() {
        onlineNumber--;
        clients.remove(userId);
        try {
//            Map<String, Object> map1 = Maps.newHashMap();
//            map1.put("messageType", 2);
//            map1.put("onlineUsers", clients.keySet());
//            map1.put("userId", userId);
//            sendMessageAll(JSON.toJSONString(map1), userId);

            // 构建消息，放入消息列表存储起来
//            String tos = clients.keySet().stream().collect(Collectors.joining(","));
//            Message message = new Message(userId + MessageType.OFFLINE.getKey(),userId,tos,new Date());
//            saveMessage(message);

        } catch (Exception e) {
            logger.error(userId + "下线的时间通知所有人发生错误", e.getMessage());
            e.printStackTrace();
        }
        logger.info("有连接关闭！当前在线人数：" + clients.size());
    }

    @OnMessage
    public void onMessage(String msg, Session session) {
        try {
            logger.info("来自客户端的消息：" + msg + "客户端的ID是：" + session.getId());
            System.out.println("------------ ：" + msg);

//            JSONObject jsonObject = JSONObject.parseObject(msg);
//            String textMessage = jsonObject.getString("message");
//            String fromUserId = jsonObject.getString("userId");
//            String toUserId = jsonObject.getString("to");
//
//            // 如果不是发给所有人，那么就发给某个人
//            // messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
//            Map<String, Object> map1 = Maps.newHashMap();
//            map1.put("messageType", 4);
//            map1.put("textMessage", textMessage);
//            map1.put("fromUserId", fromUserId);
//            if (toUserId.equals("All")) {
//                map1.put("toUserId", "所有人");
//                sendMessageAll(JSON.toJSONString(map1), fromUserId);
//            } else {
//                map1.put("toUserId", toUserId);
//                System.out.println("开始推送消息给：" + toUserId);
//                sendMessageTo(JSON.toJSONString(map1), toUserId);
//            }

            // 构建消息，放入消息列表存储起来
//            String tos = clients.keySet().stream().collect(Collectors.joining(","));
//            Message message = new Message(msg,userId,tos,new Date());
            Message message = JSONObject.parseObject(msg, Message.class);
            saveMessage(message);
            // 发送
            sendMessageAll(JSONObject.toJSONString(messageList),userId);

        } catch (Exception e) {
            logger.error(userId + "发送消息失败", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * @return void
     * @description 发消息
     * @author Johnnie Wind
     * @date 2021/4/7 10:44
     * @Param [toJSONString, userId]
     */
    public void sendMessageTo(String message, String toUserId) {
        for (WebSocket item : clients.values()) {
            //    System.out.println("在线人员名单  ："+item.userId.toString());
            if (item.userId.equals(toUserId)) {
                item.session.getAsyncRemote().sendText(message);
                break;
            }
        }
    }

    /**
     * @return void
     * @description 群发消息
     * @author Johnnie Wind
     * @date 2021/4/7 10:39
     * @Param [toJSON, userId]
     */
    public void sendMessageAll(String message, String fromUserId) {
        for (WebSocket item : clients.values()) {
            item.session.getAsyncRemote().sendText(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineNumber;
    }

    public static synchronized Set<String> getOnlineUserIds() {
        return clients.keySet();
    }

    /**
     * @description 存储消息
     * @author Johnnie Wind
     * @date 2021/4/7 22:25
     * @Param [userId, message]
     * @return void
     */
    public void saveMessage(Message message){
        messageList.add(message);
    }
}
